#ifndef __C_PSO_H__
#define __C_PSO_H__

#include <stdlib.h>

// This controls the ratio between movement and inertia
#define MOVE_RAT .9

// This controls the number of swarms used
#define N_SWARMS 16

// This controls the rate at which particles are exchanged
#define CROSS_RATE .001

// This is the number of dimensions contained in the error space
#define DIM 3

// This is the number or particles contained in each swarm
#define N 32

// This defines the maximum random startup value for the parameters of particles
#define MAX_VAL 300

// This controls the weight for direction of the swarm best and the individual
// particle respectively.
#define BEST_WEIGHT .1
#define IND_WEIGHT .1

#define frand(x) (((double)rand())/RAND_MAX)

// This controls the type of error space searching
// either double, float, or int.
#define TYPE_FLOAT
#ifdef TYPE_FLOAT
typedef float pso_type;
#else
#ifdef TYPE_DOUBLE
typedef double pso_type;
#else
typedef int pso_type;
#endif
#endif

// This structure is what holds the data for each particle in the swarm
typedef struct {
	pso_type location[DIM];
	float fitness;
	pso_type best_location[DIM];
	float best_fitness;
	pso_type inertia[DIM];
} pso_part;

// This structure contains a swarm and all bookkeeping related to the swarm
typedef struct {
	pso_part part_swarm[N];
	pso_part *best;
} pso_swarm;

// This function determines the fitness of the individual
void calc_fitness(pso_part *particle);

// This function calls calc_fitness on the entire swarm
void calc_fitness_swarm(pso_swarm *swarm);

// This function moves an individual by a given amount
void move_particle(pso_part *particle, pso_type move[DIM]);

// This function caculates required move for a particle and move it
void calc_move_particle(pso_part *particle, pso_part *best);

// This function calls calc_move_particle on entire swarm
void move_swarm(pso_swarm *swarm);

// This function checks whether an update is required for the given particle
// and updates if needed
void check_best(pso_part *new_part, pso_part **best); 

// This function will perform a swap between to swarms, only called when needed
void swap_part(pso_swarm *swarm1, pso_swarm *swarm2);

// This function initializes a particle with random startup values between 
// -MAX_VAL and MAX_VAL
void init_part(pso_part *particle);

// This function will initialize and entire swarm
void init_swarm(pso_swarm *swarm);

#endif //__C_PSO_H__
